package com.stable.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.stable.constant.RedisConstant;
import com.stable.es.dao.base.EsProBarInfoDao;
import com.stable.spider.eastmoney.EastHsgtcgSpider;
import com.stable.utils.RedisUtil;
import com.stable.utils.TradeDateUtil;
import com.stable.vo.EastHsgtcg;
import com.stable.vo.EastHsgtcgDetail;
import com.stable.vo.bus.StockBaseInfo;
import com.stable.vo.spi.req.EsQueryPageReq;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.Semaphore;
import java.util.stream.Collectors;

@Service("EastHsgtcgService")
@Log4j2
public class EastHsgtcgService {
    @Autowired
    private EsProBarInfoDao esProBarInfoDao;

    @Autowired
    private EastHsgtcgSpider eastHsgtcgSpider;

    @Autowired
    private RedisUtil redisUtil;

    private final Semaphore semapProBar = new Semaphore(1);


    public List<EastHsgtcg> queryList(String queryDate, String code, String hyname, EsQueryPageReq queryPage) {
        log.info("page queryDate={},code={},hyname={},sortName:{} ,SIZE:{}", queryDate, code, hyname, queryPage.getSortName(), queryPage.getPageSize());
        List<EastHsgtcg> allList = new ArrayList<>();

        if (StringUtils.isNotBlank(code)) {
            allList.addAll(eastHsgtcgSpider.getHSGTCG(queryPage.getPageSize(), queryDate, queryPage.getSortName())
                    .stream()
                    .filter(data -> StringUtils.equals(data.getCode(), code))
                    .map(detail -> {
                        Object stock_basic = redisUtil.hGet("stock_basic", detail.getCode());
                        StockBaseInfo stockBaseInfo = JSON.parseObject((String) stock_basic, StockBaseInfo.class);
                        detail.setGsld(stockBaseInfo.getGsld());
                        return detail;
                    })
                    .collect(Collectors.toList()));
        } else {
            allList.addAll(eastHsgtcgSpider.getHSGTCG(queryPage.getPageSize(), queryDate, queryPage.getSortName())
                    .stream().map(detail -> {
                        Object stock_basic = redisUtil.hGet("stock_basic", detail.getCode());
                        StockBaseInfo stockBaseInfo = JSON.parseObject((String) stock_basic, StockBaseInfo.class);
                        detail.setGsld(stockBaseInfo.getGsld());
                        return detail;
                    }).collect(Collectors.toList()));
        }
        if (StringUtils.isNotBlank(hyname)) {
            List<EastHsgtcg> collect = allList.stream().filter(data -> StringUtils.equals(data.getHyname(), hyname)).collect(Collectors.toList());
            allList.clear();
            allList.addAll(collect);
        }

        List<EastHsgtcg> mockList = Arrays.asList(new EastHsgtcg("mock01", "mock"), new EastHsgtcg("mock02", "mock"), new EastHsgtcg("mock03", "mock"),
                new EastHsgtcg("mock04", "mock"), new EastHsgtcg("mock05", "mock"), new EastHsgtcg("mock06", "mock"), new EastHsgtcg("mock07", "mock"),
                new EastHsgtcg("mock08", "mock"), new EastHsgtcg("mock09", "mock"), new EastHsgtcg("mock10", "mock"));
        allList.addAll(mockList);

        Map<Object, Object> guzhiMark = redisUtil.hGetAll(RedisConstant.hsgtcg_mark);
        allList.stream().forEach(data -> {
            EastHsgtcg redisData = JSON.parseObject((String) guzhiMark.get(data.getCode()), EastHsgtcg.class);
            if (!Objects.isNull(redisData)) {
                data.setGuzhi(redisData.getGuzhi());
                data.setMark(redisData.getMark());
            }
        });
        return allList;
    }

    public void editMark(String code, EastHsgtcg eastHsgtcg) {
        redisUtil.hPut(RedisConstant.hsgtcg_mark, code, JSON.toJSONString(eastHsgtcg));
    }


    //分析沪港通持续买入3天以上的数据
    public List<EastHsgtcgDetail> analyseHsgtcg(String queryDate, String code, String name, int size, EsQueryPageReq queryPage) {
        log.info("page queryDate={},code={},name={},size={},sortName:{} ,pageSIZE:{}", queryDate, code, name, size, queryPage.getSortName(), queryPage.getPageSize());
        if (StringUtils.isEmpty(queryDate)) {
            queryDate = TradeDateUtil.getNearTradeDate(0);
        }
        List<EastHsgtcgDetail> result = new ArrayList<>();
        String getHsgtcgContinueBuyDays = (String) redisUtil.hGet(RedisConstant.hsgtcg_continue_buy_days_map, queryDate);
        if (StringUtils.isNotBlank(getHsgtcgContinueBuyDays) && !getHsgtcgContinueBuyDays.equals("[]")) {
            JSONArray array = JSON.parseArray(getHsgtcgContinueBuyDays);
            for (int i = 0; i < array.size(); i++) {
                EastHsgtcgDetail redisData = JSON.parseObject(array.get(i).toString(), EastHsgtcgDetail.class);
                result.add(redisData);
            }
        } else {
            List<EastHsgtcg> shareSZ = eastHsgtcgSpider.getHSGTCG(600, TradeDateUtil.getNearTradeDate(0), "LTZB"); //根据占流通股排序得到所有数据

            List<EastHsgtcg> errorList = new ArrayList<>();
            analyseContinueBuyDays(result, shareSZ, errorList);
            if (errorList.size() > 0) { //第1轮错误后，再执行1次
                analyseContinueBuyDays(result, errorList, errorList);
            }

            result = result.stream().filter(detail -> detail.getContinueBuyDaysCount() >= size)
                    .map(detail -> {
                        Object stock_basic = redisUtil.hGet("stock_basic", detail.getCode());
                        StockBaseInfo stockBaseInfo = JSON.parseObject((String) stock_basic, StockBaseInfo.class);
                        detail.setGsld(stockBaseInfo.getGsld());
                        return detail;
                    })
                    .sorted(Comparator.comparing(EastHsgtcgDetail::getContinueBuyDaysCount))
                    .collect(Collectors.toList());

            redisUtil.hPut(RedisConstant.hsgtcg_continue_buy_days_map, TradeDateUtil.getNearTradeDate(0), JSON.toJSONString(result));
        }
        return result;
    }

    private void analyseContinueBuyDays(List<EastHsgtcgDetail> result, List<EastHsgtcg> shareSZ, List<EastHsgtcg> errorList) {
        for (EastHsgtcg hsgtcg : shareSZ) {
            try {
                Thread.sleep(250);
                List<EastHsgtcgDetail> hsgtcgDetail = eastHsgtcgSpider.getHSGTCGDetail(hsgtcg.getCode());

                int continueBuyDaysCount = 0;
                EastHsgtcgDetail firstDayDetail = null;
                for (EastHsgtcgDetail detail : hsgtcgDetail) {
                    if (continueBuyDaysCount == 0) {
                        firstDayDetail = detail;
                    }
                    if (detail.getShareholdpriceone().intValue() < 0) {
                        firstDayDetail.setContinueBuyDaysCount(continueBuyDaysCount);
                        result.add(firstDayDetail);
                        break;
                    } else {
                        continueBuyDaysCount++;
                    }
                }
            } catch (RuntimeException | InterruptedException e) {
                log.error("error:{}, {}", hsgtcg.getCode(), hsgtcg.getName(), e);
                errorList.add(hsgtcg);
            }
        }
    }

}
